package com.sn.author.service.impl;

import com.alibaba.fastjson.JSON;
import com.sn.author.common.enums.LoginStatusEnum;
import com.sn.author.common.enums.StatusEnum;
import com.sn.author.common.enums.TaskTypeEnum;
import com.sn.author.common.enums.UploadTypeEnum;
import com.sn.author.common.exception.BadRequestException;
import com.sn.author.dao.DyAccountMapper;
import com.sn.author.dao.ImportAccountMapper;
import com.sn.author.dao.ImportVideoMapper;
import com.sn.author.domain.BaseResult;
import com.sn.author.domain.dto.ImportDTO;
import com.sn.author.domain.entity.DyAccount;
import com.sn.author.domain.entity.ImportAccount;
import com.sn.author.domain.entity.ImportVideo;
import com.sn.author.domain.taskEntity.TaskModel;
import com.sn.author.domain.taskEntity.VideoInfo;
import com.sn.author.service.dao.TaskService;
import com.sn.author.service.dao.UploadService;
import com.sn.author.utils.Analysis;
import com.sn.author.utils.PhoneFormatCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author xiaom
 * @Date 2020/9/17 16:31
 * @Version 1.0.0
 * @Description <>
 **/
@Service
@Slf4j
public class UploadServiceImpl implements UploadService {

    @Resource
    private ImportAccountMapper importAccountMapper;

    @Resource
    private ImportVideoMapper importVideoMapper;

    @Resource
    private DyAccountMapper dyAccountMapper;

    private final TaskService taskService;

    public UploadServiceImpl(TaskService taskService) {
        this.taskService = taskService;
    }

    @Override
    public BaseResult<ImportDTO> upload(MultipartFile file, UploadTypeEnum typeEnum) {
        ImportDTO result;

        switch (typeEnum){
            case ACCOUNT_TYPE:
                result = importAccount(file);
                break;
            case VIDEO_TYPE:
                result = importVideoUrl(file);
                break;
            case DY_ACCOUNT_TYPE:
                result = importDyAccount(file);
                break;
            default:
                throw new BadRequestException("异常上传文件类型");
        }
        return BaseResult.success(result);
    }

    private ImportDTO importDyAccount(MultipartFile file) {
        List<DyAccount> accountList = parserExcelFile(file);
        log.info("解析到的文件内容:{}",JSON.toJSONString(accountList));
        return new ImportDTO(insertDyAccount(accountList),new ArrayList<>(),UploadTypeEnum.DY_ACCOUNT_TYPE);
    }

    private ImportDTO importVideoUrl(MultipartFile file) {
        List<String> videoList = parserFile(file);
        log.info("导入的视频数量:{}",videoList.size());
        //异步调用dy api 获取视频点赞数量
        taskService.generateJobToPool(buildTaskModel(videoList),-1L);
        return new ImportDTO(insertVideo(videoList),videoList,UploadTypeEnum.VIDEO_TYPE);
    }

    private List<TaskModel> buildTaskModel(List<String> videoList) {
        return videoList.stream().map(s -> {
            TaskModel model = new TaskModel();
            model.setTaskType(TaskTypeEnum.VIDEOINFO.getType());
            model.setTaskId("-1");
            model.setTaskParam(new VideoInfo(s));
            return model;
        }).collect(Collectors.toList());
    }

    private List<DyAccount> parserExcelFile(MultipartFile file){

        try {
            List<List<Object>> list = Analysis.getCourseListByExcel(file);
            if(list.isEmpty()){
                return new ArrayList<>();
            }
            return parserToModel(list);
        }catch (Exception e){
            log.error("解析【抖音账号】 excel文件失败 e:{}",e.getMessage());
            e.printStackTrace();
            throw new BadRequestException("上传失败");
        }

    }

    /**
     * "序号","昵称","用户ID","抖音ID","头像"
     * @param list
     * @return
     */
    private List<DyAccount> parserToModel(@NonNull List<List<Object>> list) {

        List<DyAccount> result = new ArrayList<>();

        list.forEach(item -> {
            DyAccount dyAccount = new DyAccount();
            dyAccount.setNickName(item.get(1).toString());
            dyAccount.setUserId(Long.parseLong(item.get(2).toString()));
            dyAccount.setDyUnid(item.get(3).toString());
            dyAccount.setPortrait(item.get(4).toString());
            result.add(dyAccount);
        });

        return result;
    }

    private List<String> parserFile(MultipartFile file) {
        try {
            //解析文件
            List<String> list = Analysis.parserFileContent(file);
            if(list.isEmpty()){
                return new ArrayList<>();
            }
            log.info("上传的文件列表:{}", JSON.toJSONString(list));
            //写入到数据库
            return list;
        }catch (Exception e){
            log.error("解析excel文件失败 e:{}",e.getMessage());
            e.printStackTrace();
            throw new BadRequestException("解析文件失败");
        }
    }

    private ImportDTO importAccount(MultipartFile file){
        List<String> accountList = parserFile(file);
        log.info("导入的账号数量:{}",accountList.size());
        return new ImportDTO(insertAccount(accountList),accountList,UploadTypeEnum.ACCOUNT_TYPE);
    }

    private Integer insertDyAccount(List<DyAccount> accountList) {

        Set<String> alreadyNickNameSet = new HashSet<>();
        List<DyAccount> list = dyAccountMapper.selectAll();
        if(list != null){
            list.forEach(item -> alreadyNickNameSet.add(item.getNickName()));
        }

        List<DyAccount> insertList = accountList.stream().filter(f ->
                f != null && !alreadyNickNameSet.contains(f.getNickName())).collect(Collectors.toList());
        if(!insertList.isEmpty()){
            dyAccountMapper.batchInsert(insertList);
        }
        return insertList.size();
    }

    private Integer insertVideo(List<String> list){
        Set<String> alreadyPhoneSet = new HashSet<>();
        //获取已有的视频地址,防止重复
        List<ImportVideo> importVideos = importVideoMapper.selectAll();
        if(importVideos != null){
            importVideos.forEach(item -> alreadyPhoneSet.add(item.getVideoUrl()));
        }

        List<ImportVideo> insertList = list.stream().filter(f ->
                !alreadyPhoneSet.contains(f))
                .map(s -> {
                    ImportVideo importAccount = new ImportVideo();
                    injectDefaultAttr(importAccount);
                    importAccount.setVideoUrl(s);
                    importAccount.setStatus(StatusEnum.NORMAL.getStatus());
                    return importAccount;
                }).collect(Collectors.toList());

        if(!insertList.isEmpty()){
            importVideoMapper.batchInsert(insertList);
        }
        return insertList.size();
    }

    private Integer insertAccount(List<String> list) {

        Set<String> alreadyPhoneSet = new HashSet<>();
        //获取已有的手机号码,防止重复
        List<ImportAccount> importAccounts = importAccountMapper.selectAll();
        if(importAccounts != null){
            importAccounts.forEach(item -> alreadyPhoneSet.add(item.getPhone()));
        }

        List<ImportAccount> insertList = list.stream().map(s -> s.split("----")).filter(f ->
                !alreadyPhoneSet.contains(f[0])
                        && PhoneFormatCheckUtils.isChinaPhoneLegal(f[0]))
                .map(s -> {
                    ImportAccount importAccount = new ImportAccount();
                    injectDefaultAttr(importAccount);
                    importAccount.setPhone(s[0]);
                    importAccount.setPassword(s[1]);
                    importAccount.setArea(s[2]);
                    importAccount.setAreaCode(s[3]);
                    importAccount.setStatus(StatusEnum.NORMAL.getStatus());
                    importAccount.setLoginStatus(LoginStatusEnum.NO_LOGIN.getStatus());
                    return importAccount;
                }).collect(Collectors.toList());

        if(!insertList.isEmpty()){
            importAccountMapper.batchInsert(insertList);
        }
        return insertList.size();
    }
}
